﻿using EnvDTE;
using Sasa.QualityTools.CodeAnalysis.Common;
using Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.VisualStudio
{
    public class Project
    {
        protected EnvDTE.Project project;


        public virtual bool ShouldAnalyze
        {
            get
            {
                return true;
            }
        }

        public string Name
        {
            get { return project.Name; }
        }

        public string Path
        {
            get { return project.FullName; }
        }

        public string TargetDir
        {
            get
            {
                try
                {
                    var directory = project.Properties.Item("FullPath").Value.ToString();
                    var outputPath = project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();
                    return System.IO.Path.GetFullPath(System.IO.Path.Combine(directory, outputPath));
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Failed to get the directory that is generated assembly of '{0}' project.", project.Name);
                    return null;
                }
            }
        }

        public virtual string AssemblyPath
        {
            get
            {
                try
                {
                    var outputFileName = project.Properties.Item("OutputFileName").Value.ToString();
                    return System.IO.Path.Combine(TargetDir, outputFileName);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Failed to get assembly path of '{0}' project.", project.Name);
                    return null;
                }
            }
        }

        public string ConfigurationPath
        {
            get { return System.IO.Path.Combine(System.IO.Path.GetDirectoryName(project.FullName), "CodeAnalysis", "CodeAnalysisConfiguration.xml"); }
        }

        public virtual IEnumerable<string> DependencyDirectories
        {
            get { return new List<string>(); }
        }

        public Solution Solution
        {
            get
            {
                return new Solution(project.DTE.Solution);
            }
        }


        protected Project(EnvDTE.Project project)
        {
            if (project == null) throw new ArgumentNullException("project");

            this.project = project;
        }


        public static Project CreateInstance(EnvDTE.Project project)
        {
            if (project == null) throw new ArgumentNullException("project");

            if (String.Equals(project.Kind, "{E24C65DC-7377-472b-9ABA-BC803B73C61A}", StringComparison.OrdinalIgnoreCase))
            {
                return new WebSiteProject(project);
            }
            else if (String.Equals(project.Kind, "{CC5FD16D-436D-48AD-A40C-5A424C6E3E79}", StringComparison.OrdinalIgnoreCase))
            {
                return new AzureProject(project);
            }

            var extenderNames = project.ExtenderNames as object[];
            if (extenderNames != null)
            {
                foreach (var extenderName in extenderNames)
                {
                    var name = Convert.ToString(extenderName);
                    if (name == "SilverlightProject")
                    {
                        return new SilverlightProject(project);
                    }
                }
            }

            return new Project(project);
        }

        public void Save()
        {
            project.Save();
        }

        public bool Build()
        {
            var builder = project.DTE.Solution.SolutionBuild;
            builder.BuildProject(builder.ActiveConfiguration.Name, project.UniqueName, true);
            return builder.LastBuildInfo == 0;
        }

        public void AddFromFile(string path)
        {
            project.ProjectItems.AddFromFile(path);
        }

        public ProjectItem AddFromDirectory(string path)
        {
            return new ProjectItem(project.ProjectItems.AddFromDirectory(path));
        }

        public string GetFilePathFromTypeName(string typeName)
        {
            var codeType = GetCodeTypeFromTypeName(typeName);
            var item = (codeType != null) ? codeType.ProjectItem : null;
            return (item != null) ? item.FileNames[0] : null;
        }

        //public void OpenFileByPath(string path, int? line)
        //{
        //    var name = path.Replace(Path.GetDirectoryName(project.FullName) + Path.DirectorySeparatorChar, "");
        //    var item = project.ProjectItems.Item(name);
        //    if (item.IsOpen)
        //    {
        //        item.Document.Activate();
        //    }
        //    else
        //    {
        //        var window = item.Open(EnvDTE.Constants.vsViewKindCode);
        //        window.Visible = true;
        //        window.Activate();
        //    }

        //    if (line.HasValue)
        //    {
        //        ((TextSelection)item.Document.Selection).GotoLine(line.Value);
        //    }
        //}

        //public void OpenFileByTypeName(string typeName, int? line)
        //{
        //    var codeType = GetCodeTypeFromTypeName(typeName);
        //    var item = (codeType != null) ? codeType.ProjectItem : null;
        //    if (item == null) return;

        //    if (item.IsOpen)
        //    {
        //        item.Document.Activate();
        //    }
        //    else
        //    {
        //        var window = item.Open(EnvDTE.Constants.vsViewKindCode);
        //        window.Visible = true;
        //        window.Activate();
        //    }
        //    ((TextSelection)item.Document.Selection).GotoLine((line.HasValue) ? line.Value : codeType.StartPoint.Line);
        //}

        private CodeType GetCodeTypeFromTypeName(string typeName)
        {
            if (typeName == null) throw new ArgumentNullException("typeName");

            if (project.CodeModel != null)
            {
                var name = ConvertTypeName(project.CodeModel.Language, typeName);
                return project.CodeModel.CodeTypeFromFullName(name);
            }
            else
            {
                return null;
            }
        }

        private static string ConvertTypeName(string language, string typeName)
        {
            // TODO
            return typeName;
        }
    }
}
